#include "DataParser_grid.h"
#include <QRegularExpression>


#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>

#include <QPixmap>

using namespace std;

// 1.实现虚函数
bool DataParser_grid::readFile(const QString& qFullName) {
	QFileInfo fileInfo(qFullName);
	QString qfielPath = fileInfo.absolutePath();
	QString qfileBaseName = fileInfo.baseName();
	QString suffix = fileInfo.suffix().toLower();
	bool readSuccessed = false;
	if (suffix == "jpg" || suffix == "jpeg" || suffix == "png")
		readSuccessed = read_image_to_map(qFullName, qfielPath, qfileBaseName);
	else if(suffix == "map")
		readSuccessed = read_text_to_map(qFullName);
	else if (suffix == "json")
		readSuccessed = read_map_routing_res(qFullName);
	else
		return false;
	return readSuccessed;

}

bool DataParser_grid::saveFile(const QString& qFullName){

	return true;
}
bool DataParser_grid::saveFileAs(const QString& qFullName) {
	return true;
}
void DataParser_grid::setMinMax() {

}

// 2.数据处理（公有）
vector<LineUI> DataParser_grid::getRandomPts(int width, int height, int randPtSum) {	// 计算前端读取图片作为地图时,生成txt地图文件,写入的起点终点坐标
	// 参数width表示图片的宽度,height表示图片的高度
	bool left_begin_right_end = false;	// 起点终点在两侧
	int pin_sum = height / 50 + 3;	// 生成pin的数量，默认图片高度的1/100+1：height / 100 + 1
	if (width > 200) {
		pin_sum = 8;
	}
	int left_max_dist = width;
	if (left_begin_right_end) {
		if (width < 201)
			left_max_dist = 20;
		else if (width < 501)
			left_max_dist = 40;
		else if (width < 1001)
			left_max_dist = 80;
		else if (width < 2001)
			left_max_dist = 160;
		else if (width < 4001)
			left_max_dist = 320;
	}
	if (randPtSum >= 0) pin_sum = randPtSum;
	std::vector<LineUI> result;
	for (int i = 0; i < pin_sum; i++) {
		// x取随机数，y取两侧附近的随机数
		int pt1x = rand() % left_max_dist;
		int pt1y = rand() % height;
		int pt2x = width - left_max_dist + rand() % left_max_dist;
		int pt2y = rand() % height;
		result.emplace_back(LineUI(pt1x, pt1y, pt2x, pt2y));		//写入basicData对象中
	}
	return result;
}
void DataParser_grid::setPtsFromLines(vector<LineUI>& lines, vector<QPointF>& pts) {
	pts.clear();
	int len = lines.size();
	if (len > 0) {
		if (lines[0].length() > 2000)	return;		//线段实际长度过大，不进行整数点设置
		pts = lines[0].getIntPts(true, true);
	}
	for (int i = 1; i < len; ++i) {
		vector<QPointF> one_line_pts = lines[i].getIntPts(false, true);
		pts.insert(pts.end(), one_line_pts.begin(), one_line_pts.end());
	}
}
void DataParser_grid::setPtsFromLines(vector<vector<LineUI>>& liness, vector<vector<QPointF>>& pts) {
	pts.clear();
	for (auto& lines : liness) {
		pts.emplace_back(vector<QPointF>());
		setPtsFromLines(lines, pts.back());
	}
}

bool DataParser_grid::write_PPDT_case(const QString& qFullName, const Data_grid* data) {
	QFile outputFile(qFullName);
	if (!outputFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
		qDebug() << "无法打开输出文件:" << qFullName;
		return false;
	}
	QTextStream out(&outputFile);
	out.setEncoding(QStringConverter::Utf8); // 设置编码为 UTF-8
	out << "$ST \n";
	for (auto& lineui : data->m_flyLines) {
		out << lineui.p1().y() << ' '  // 直接输出数值，避免中间字符串
			<< lineui.p1().x() << ' '
			<< lineui.p2().y() << ' '
			<< lineui.p2().x() << '\n';
	}
	out << "$Map \n";
	size_t height = data->m_mapSymbols.size();
	size_t width = data->m_mapSymbols.empty() ? 0 : data->m_mapSymbols[0].size();
	for (int y = 0; y < height; ++y) {
		for (int x = 0; x < width; ++x) {
			out << data->m_mapSymbols[y][x];
		}
		out << '\n';
	}
	outputFile.close();
	return true;
}
bool DataParser_grid::write_PPDT_Pre(const QString& qFullName, const vector<LineUI>& pinPairs,
	const vector<vector<QPointF>>& pathPts, const vector<QString>& mapSymbols) {
	//新建一个文件，覆盖写入map_size，pins，prePath
	QFile outputFile(qFullName);
	if (!outputFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
		qDebug() << "无法打开输出文件:" << qFullName;
		return false;
	}
	QTextStream out(&outputFile);
	out.setEncoding(QStringConverter::Utf8); // 设置编码为 UTF-8

	// 使用 QTextStream 写入，保持与原来完全相同的格式
	out << "{\n"; // 外层括号===========================================================================

	// 1.写入map_size
	if (mapSymbols.empty() || mapSymbols[0].isEmpty()) {
		qDebug() << "m_data->m_mapSymbols(地图字符表)为空";
		outputFile.close();
		return false;
	}
	out << "  \"map_size\": [" << mapSymbols.size() << ", " << mapSymbols[0].size() << "],\n";

	// 2.写入 m_Pins
	out << "  \"pins\": [\n"; // "pins"键开始
	for (size_t i = 0; i < pinPairs.size(); ++i) {
		out << "    ["; // 单个pin数组开始
		out << pinPairs[i].p1().y() << ", " << pinPairs[i].p1().x() << ", " << 0 << ", "; // start的x, y, l
		out << pinPairs[i].p2().y() << ", " << pinPairs[i].p2().x() << ", " << 0; // end的x, y, l
		if (i < pinPairs.size() - 1) {
			out << "],\n"; // 非最后一个pin，添加逗号
		}
		else {
			out << "]\n"; // 最后一个pin，不添加逗号
		}
	}
	out << "  ],\n"; // "pins"键结束

	// 3.写入prePath
	out << "  \"prePath\": {\n"; // "path"键开始
	for (size_t i = 0; i < pathPts.size(); ++i) {
		out << "    \"" << i << "\": [\n"; // 路径键开始
		for (size_t j = 0; j < pathPts[i].size(); ++j) {
			out << "      [" << pathPts[i][j].y() << ", " << pathPts[i][j].x() << "]";
			if (j < pathPts[i].size() - 1) {
				out << ",\n"; // 非最后一行，添加逗号
			}
			else {
				out << "\n"; // 最后一行，不添加逗号
			}
		}
		if (i < pathPts.size() - 1) {
			out << "    ],\n"; // 非最后一条路径，添加逗号
		}
		else {
			out << "    ]\n"; // 最后一条路径，不添加逗号
		}
	}
	out << "  },\n"; // "prePath"键结束
	outputFile.close();
	return true;
}
bool DataParser_grid::write_PPDT_Res(const QString& qFullName, const vector<vector<QPointF>>& pathPts, const vector<QString>& mapSymbols) {
	// 打开文件追加写入resPath和map
	QFile outputFile(qFullName);
	if (!outputFile.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Append)) {
		qDebug() << "无法打开输出文件:" << qFullName;
		return false;
	}
	QTextStream out(&outputFile);
	out.setEncoding(QStringConverter::Utf8); // 设置编码为 UTF-8

	//4.写入resPath
	out << "  \"resPath\": {\n"; // "path"键开始
	for (size_t i = 0; i < pathPts.size(); ++i) {
		out << "    \"" << i << "\": [\n"; // 路径键开始
		for (size_t j = 0; j < pathPts[i].size(); ++j) {
			out << "      [" << pathPts[i][j].y() << ", " << pathPts[i][j].x() << "]";
			if (j < pathPts[i].size() - 1) {
				out << ",\n"; // 非最后一行，添加逗号
			}
			else {
				out << "\n"; // 最后一行，不添加逗号
			}
		}
		if (i < pathPts.size() - 1) {
			out << "    ],\n"; // 非最后一条路径，添加逗号
		}
		else {
			out << "    ]\n"; // 最后一条路径，不添加逗号
		}
	}
	out << "  },\n"; // "resPath"键结束

	//5.写入 map
	if (mapSymbols.empty() || mapSymbols[0].isEmpty()) {
		qDebug() << "m_data->m_mapSymbols(地图字符表)为空";
		outputFile.close();
		return false;
	}
	out << "  \"map\": [\n"; // "map"键开始
	for (size_t i = 0; i < mapSymbols.size(); ++i) {
		out << "    [\n"; // 单行地图数据开始
		for (size_t j = 0; j < mapSymbols[i].size(); ++j) {
			int symbol_int = mapSymbols[i][j] == '#' ? 1 : 0;
			out << "      [" << i << ", " << j << ", " << 0 << ", " << symbol_int << "]";
			if (j < mapSymbols[i].size() - 1) {
				out << ",\n"; // 非最后一个点，添加逗号
			}
			else {
				out << "\n"; // 最后一个点，不添加逗号
			}
		}
		if (i < mapSymbols.size() - 1) {
			out << "    ],\n"; // 非最后一行，添加逗号
		}
		else {
			out << "    ]\n"; // 最后一行，不添加逗号
		}
	}
	out << "  ]\n"; // "map"键结束
	out << "}\n";   // 外层括号外层括号===========================================================================
	outputFile.close();
	return true;
}

bool DataParser_grid::read_text_to_map(const QString& qFullName) {
	QFile qTxtFile(qFullName);
	if (!qTxtFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
		qWarning() << "Failed to open txt file! ";
		return false;
	}
	vector<numbers> pinCoordinates;
	QTextStream in(&qTxtFile);
	bool in_start_end = false;
	bool in_map = false;
	bool in_others = false;
	int x = 0, y = 0;
	while (!in.atEnd()) {
		QString line = in.readLine().trimmed();
		if (line.isEmpty()) continue;  // 跳过空行
		if (line.startsWith("$ST")) {
			in_start_end = true;
			in_map = false;
			in_others = false;
			continue;
		}
		else if (line.startsWith("$Map")) {
			y = 0;
			in_start_end = false;
			in_map = true;
			in_others = false;
			continue;
		}
		else if (line.startsWith("$")) {  // 未知的数据标记
			in_start_end = false;
			in_map = false;
			in_others = true;
			continue;
		}
		QTextStream lineStream(&line);
		numbers nums;
		if (in_start_end) {
			lineStream >> nums.num1 >> nums.num2 >> nums.num3 >> nums.num4;
			if (lineStream.status() == QTextStream::Ok) {
				pinCoordinates.push_back(nums);
			}
		}
		else if (in_map) {
			m_data->m_mapSymbols.emplace_back(line);
			for (x = 0; x < line.size(); ++x) {
				if (line[x] == '#')
					m_data->m_Pts.emplace_back(QPointF(x, y));
			}
			y++;
		}
		else if (in_others) {
			continue;
		}
	}
	qTxtFile.close();
	//m_data赋值
	//维护m_data中的数据
		//1.维护飞线
	for (auto& nums : pinCoordinates) {
		m_data->m_flyLines.emplace_back(LineUI(nums.num2, nums.num1, nums.num4, nums.num3));
	}
	//维护地图字符（在读取时维护）
	m_data->minPt = QPointF(0, 0);
	m_data->maxPt = QPointF(x, y);
	return true;
}
bool DataParser_grid::read_image_to_map(const QString& qFullName, const QString& qfielPath,const QString& qBaseName) {
	QString textMapName = qBaseName + ".map";
	QString textMapFullName = qfielPath + "/" + textMapName;
	QImage image(qFullName);
	if (image.isNull()) {
		return false;
	}
	QFile outputFile(textMapFullName);
	if (!outputFile.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) {
		return false;
	}
	QTextStream out(&outputFile);
	// 写入起点终点
	out << "$ST \n";
	//pin对（即飞线）,传入整数4代表随机pin数量，0代表自动数量
	m_data->m_flyLines = getRandomPts(image.width(), image.height(), m_data->m_pinSum);
	for (auto& lineui : m_data->m_flyLines) {
		out << lineui.p1().y() << ' '  // 直接输出数值，避免中间字符串
			<< lineui.p1().x() << ' '
			<< lineui.p2().y() << ' '
			<< lineui.p2().x() << '\n';
	}

	out << "$Map \n";
	for (int y = 0; y < image.height(); ++y) {
		m_data->m_mapSymbols.emplace_back(QString());
		for (int x = 0; x < image.width(); ++x) {
			QRgb pixel = image.pixel(x, y);
			int red = qRed(pixel);
			int green = qGreen(pixel);
			int blue = qBlue(pixel);
			int alpha = qAlpha(pixel);
			if (red == 255 && green == 255 && blue == 255 && alpha == 255) {
				m_data->m_mapSymbols.back() += 'o';
				out << "o";
			}
			else {
				m_data->m_mapSymbols.back() += '#';
				m_data->m_Pts.emplace_back(QPointF(x, y));
				out << "#";
			}
		}
		out << '\n';
	}
	outputFile.close();
	//m_data赋值
	m_data->minPt = QPointF(0, 0);
	m_data->maxPt = QPointF((int)image.width(), (int)image.height());
	return true;
}
bool DataParser_grid::read_map_routing_res(const QString& qFullName) {
	// 1. 读取文件
	QFile file(qFullName);
	if (!file.open(QIODevice::ReadOnly)) {
		qWarning() << "无法打开文件:" << qFullName;
		return false;
	}

	QByteArray data = file.readAll();
	file.close();

	// 2. 解析 JSON
	QJsonDocument doc = QJsonDocument::fromJson(data);
	if (doc.isNull()) {
		qWarning() << "无效的 JSON 格式";
		return false;
	}

	QJsonObject root = doc.object();

	// 3. 提取 map_size
	QJsonArray mapSize = root["map_size"].toArray();
	int height = mapSize[0].toInt();
	int width = mapSize[1].toInt();
	m_data->minPt = QPointF(0, 0);
	m_data->maxPt = QPointF((int)width, (int)height);
	// 4. 提取 pins
	for (const QJsonValue& pinVal : root["pins"].toArray()) {
		QJsonArray onePin = pinVal.toArray();
		int num1 = onePin[0].toInt();
		int num2 = onePin[1].toInt();
		int num4 = onePin[3].toInt();
		int num5 = onePin[4].toInt();
		m_data->m_flyLines.emplace_back(LineUI(num2, num1, num5, num4));
	}

	// 5. 提取 prePath

	//QList list = root["prePath"].toObject().keys();
	//for (const QString& key : list) {
	//	m_data->m_wiresPts.emplace_back(vector<QPointF>());
	//	for (const QJsonValue& pointVal : root["prePath"].toObject()[key].toArray()) {
	//		QJsonArray pt = pointVal.toArray();
	//		int num1 = pointVal[0].toInt();
	//		int num2 = pointVal[1].toInt();
	//		m_data->m_wiresPts.back().emplace_back(QPointF(num2, num1));
	//	} 
	//}
	
	// 直接使用 QJsonObject 的迭代器，完全避免 QList
	QJsonObject prePathObj = root["prePath"].toObject();
	for (auto it = prePathObj.begin(); it != prePathObj.end(); ++it) {
		const QString& key = it.key();  // 直接获取键
		QJsonArray pointArray = it.value().toArray();  // 直接获取值
		m_data->m_wiresPts.emplace_back(vector<QPointF>());
		for (const QJsonValue& pointVal : pointArray) {
			QJsonArray pt = pointVal.toArray();
			if (pt.size() >= 2) {
				int num1 = pt[0].toInt();  // 修正：应该是 pt[0]，不是 pointVal[0]
				int num2 = pt[1].toInt();  // 修正：应该是 pt[1]，不是 pointVal[1]
				m_data->m_wiresPts.back().emplace_back(QPointF(num2, num1));
			}
		}
	}

	// 6. 提取 resPath

	//QList list1 = root["resPath"].toObject().keys();
	//for (const QString& key : list1) {
	//	m_data->m_resWiresPts.emplace_back(vector<QPointF>());
	//	for (const QJsonValue& pointVal : root["resPath"].toObject()[key].toArray()) {
	//		QJsonArray pt = pointVal.toArray();
	//		int num1 = pointVal[0].toInt();
	//		int num2 = pointVal[1].toInt();
	//		m_data->m_resWiresPts.back().emplace_back(QPointF(num2, num1));
	//	}
	//}

	// 直接使用 QJsonObject 的迭代器，完全避免 QList
	QJsonObject resPathObj = root["resPath"].toObject();
	for (auto it = resPathObj.begin(); it != resPathObj.end(); ++it) {
		const QString& key = it.key();  // 直接获取键
		QJsonArray pointArray = it.value().toArray();  // 直接获取值
		m_data->m_resWiresPts.emplace_back(vector<QPointF>());
		for (const QJsonValue& pointVal : pointArray) {
			QJsonArray pt = pointVal.toArray();
			if (pt.size() >= 2) {
				int num1 = pt[0].toInt();  // 修正：应该是 pt[0]，不是 pointVal[0]
				int num2 = pt[1].toInt();  // 修正：应该是 pt[1]，不是 pointVal[1]
				m_data->m_resWiresPts.back().emplace_back(QPointF(num2, num1));
			}
		}
	}

	// 7. 提取 map 数据
	QVector<QVector<QVector<int>>> mapData;
	for (const QJsonValue& rows : root["map"].toArray()) {
		for (const QJsonValue& pt_json : rows.toArray()) {
			QJsonArray pt = pt_json.toArray();	//x，y,layer,obs
			int num1 = pt[0].toInt();
			int num2 = pt[1].toInt();
			int num4 = pt[3].toInt();
			if (num4 == 1) {		//是障碍物
				m_data->m_Pts.emplace_back(QPointF(num2, num1));
			}
		}
	}
	return true;
}


